package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.enumeration.ReportSpaceHomeAuditStatusEnum;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.venueservice.consts.CommonConstants;
import com.eastfair.venueservice.dao.HomeBuilderDrawingCategoryAuditMapper;
import com.eastfair.venueservice.dto.*;
import com.eastfair.venueservice.entity.HomeBuilderDrawingCategoryAudit;
import com.eastfair.venueservice.enumeration.HomeBuilderDrawingCategoryAuditAuditStatusEnum;
import com.eastfair.venueservice.enumeration.HomeBuilderDrawingCategoryAuditDrawingSourceEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.HomeBuilderDrawingCategoryAuditVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 主场搭建商图纸分类审核记录
 * </p>
 *
 * @author dqq
 * @date 2023-04-28
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class HomeBuilderDrawingCategoryAuditServiceImpl extends SuperServiceImpl<HomeBuilderDrawingCategoryAuditMapper, HomeBuilderDrawingCategoryAudit> implements HomeBuilderDrawingCategoryAuditService {

    @Resource
    private HomeBuilderDrawingAuditService homeBuilderDrawingAuditService;

    @Resource
    private HomeBuilderDrawingCategoryAuditHistoryService homeBuilderDrawingCategoryAuditHistoryService;

    @Resource
    private ExhibitionSpaceDrawingService exhibitionSpaceDrawingService;

    @Resource
    private VenueManageReportDrawingCategoryAuditService venueManageReportDrawingCategoryAuditService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<HomeBuilderDrawingCategoryAudit> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(HomeBuilderDrawingCategoryAudit model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (model.getReportTime() == null) {
            model.setReportTime(LocalDateTime.now());
        }
        return R.successDef();
    }

    @Override
    public Page<HomeBuilderDrawingCategoryAuditVO> listCategoryAuditVO(PageParams<HomeBuilderDrawingCategoryAuditDTO> pageParams) {
        log.info("listCategoryAuditVO - 分页查询图纸分类审核列表VO, pageParams={}", pageParams);
        Page<HomeBuilderDrawingCategoryAudit> pageParam = pageParams.buildPage();
        QueryWrapper<HomeBuilderDrawingCategoryAudit> queryWrapper = createQueryWrapper(pageParams.getModel());
        Page<HomeBuilderDrawingCategoryAudit> page = page(pageParam, queryWrapper);
        Page<HomeBuilderDrawingCategoryAuditVO> voPage = new Page<>();
        BeanUtil.copyProperties(page, voPage);
        List<HomeBuilderDrawingCategoryAudit> list = page.getRecords();
        if (list == null || list.isEmpty()) {
            return voPage;
        }
        List<HomeBuilderDrawingCategoryAuditVO> voList = list
                .stream()
                .map(homeBuilderDrawingCategoryAudit -> BeanUtil.toBean(homeBuilderDrawingCategoryAudit, HomeBuilderDrawingCategoryAuditVO.class))
                .collect(Collectors.toList());
        voPage.setRecords(voList);
        return voPage;
    }

    @Override
    public List<HomeBuilderDrawingCategoryAudit> listHomeBuilderDrawingCategoryAudit(HomeBuilderDrawingCategoryAuditDTO query) {
        QueryWrapper<HomeBuilderDrawingCategoryAudit> queryWrapper = createQueryWrapper(query);
        return list(queryWrapper);
    }

    @Override
    public List<HomeBuilderDrawingCategoryAudit> listByReportIdAndSource(Long reportId, HomeBuilderDrawingCategoryAuditDrawingSourceEnum drawingSource) {
        HomeBuilderDrawingCategoryAuditDTO query = new HomeBuilderDrawingCategoryAuditDTO();
        query.setReportId(reportId);
        query.setDrawingSource(drawingSource);
        return listHomeBuilderDrawingCategoryAudit(query);
    }

    @Override
    public HomeBuilderDrawingCategoryAuditVO getVOById(Long id) {
        log.info("getVOById - id 查询详情, id={}", id);
        HomeBuilderDrawingCategoryAudit homeBuilderDrawingCategoryAudit = getById(id);
        if (homeBuilderDrawingCategoryAudit == null) {
            return null;
        }
        return BeanUtil.toBean(homeBuilderDrawingCategoryAudit, HomeBuilderDrawingCategoryAuditVO.class);
    }

    @Override
    public boolean isBuilderReportSpaceAllApproved(List<HomeBuilderDrawingCategoryAudit> list) {
        if (list == null || list.isEmpty()) {
            return false;
        }
        int approvedCount = 0;
        int notNeedApproveCount = 0;
        for (HomeBuilderDrawingCategoryAudit homeBuilderDrawingCategoryAudit : list) {
            if (HomeBuilderDrawingCategoryAuditAuditStatusEnum.APPROVED.eq(homeBuilderDrawingCategoryAudit.getAuditStatus())) {
                approvedCount++;
            }
            if (HomeBuilderDrawingCategoryAuditAuditStatusEnum.NOT_NEED_AUDIT.eq(homeBuilderDrawingCategoryAudit.getAuditStatus())) {
                notNeedApproveCount++;
            }
        }
        return approvedCount + notNeedApproveCount == list.size();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveHomeBuilderDrawingCategoryAudit(HomeBuilderDrawingCategoryAuditDTO auditDTO) {
        HomeBuilderDrawingCategoryAudit homeBuilderDrawingCategoryAudit = BeanUtil.toBean(auditDTO, HomeBuilderDrawingCategoryAudit.class);
        save(homeBuilderDrawingCategoryAudit);
        // 批量保存图纸
        List<HomeBuilderDrawingAuditDTO> drawingAuditList = auditDTO.getDrawingAuditList();
        homeBuilderDrawingAuditService.saveBatch(drawingAuditList, homeBuilderDrawingCategoryAudit.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatch(List<HomeBuilderDrawingCategoryAuditDTO> list) {
        if (list == null || list.isEmpty()) {
            return false;
        }
        // 批量保存
        list.forEach(this::saveHomeBuilderDrawingCategoryAudit);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean submitBatchForBuilder(List<HomeBuilderDrawingCategoryAuditDTO> list) {
        HomeBuilderDrawingCategoryAuditDTO homeBuilderDrawingCategoryAuditDTO = list.get(0);
        Long reportId = homeBuilderDrawingCategoryAuditDTO.getReportId();
        // 查询当前图纸分类列表
        List<HomeBuilderDrawingCategoryAudit> existAuditList = listByReportIdAndSource(reportId, HomeBuilderDrawingCategoryAuditDrawingSourceEnum.BUILDER_REPORT);
        if (existAuditList == null || existAuditList.isEmpty()) {
            // 如果当前已有的图纸审核列表为为空，则是第一次提交，全部保存
            return saveBatch(list);
        }
        // 如果之前提交过
        // 重新提交审核未通过的图纸
        return resubmitBatchForBuilder(list, existAuditList, reportId);
    }

    @Override
    public boolean resubmitBatchForBuilder(List<HomeBuilderDrawingCategoryAuditDTO> list, List<HomeBuilderDrawingCategoryAudit> existAuditList, Long reportId) {
        // 重新提交之前审核未通过的数据
        // 当前准备提交的图纸分类map
        Map<Long, HomeBuilderDrawingCategoryAudit> homeBuilderDrawingCategoryAuditMap = new HashMap<>(16);
        existAuditList.forEach(homeBuilderDrawingCategoryAudit -> homeBuilderDrawingCategoryAuditMap.put(homeBuilderDrawingCategoryAudit.getDrawingId(), homeBuilderDrawingCategoryAudit));

        List<HomeBuilderDrawingCategoryAuditDTO> needResubmitList = new ArrayList<>();
        for (HomeBuilderDrawingCategoryAuditDTO needSubmitDTO : list) {
            HomeBuilderDrawingCategoryAudit existAudit = homeBuilderDrawingCategoryAuditMap.get(needSubmitDTO.getDrawingId());
            // 如果当前提交的图纸分类，不在已审核列表中，则是新提交的数据，需要提交
            if (existAudit == null) {
                needResubmitList.add(needSubmitDTO);
                continue;
            }
            homeBuilderDrawingCategoryAuditMap.remove(needSubmitDTO.getDrawingId());
            // 如果是场馆审核通过的，或者是主场审核通过场馆无需审核的图纸分类，则保持原样
            boolean notNeedResubmit = HomeBuilderDrawingCategoryAuditAuditStatusEnum.APPROVED.eq(needSubmitDTO.getAuditStatus())
                    || (HomeBuilderDrawingCategoryAuditAuditStatusEnum.NOT_NEED_AUDIT.eq(needSubmitDTO.getAuditStatus())
                    && ReportSpaceHomeAuditStatusEnum.APPROVED.eq(needSubmitDTO.getHomeAuditStatus()));
            if (notNeedResubmit) {
                continue;
            }
            needResubmitList.add(needSubmitDTO);
        }
        // 已审核的记录不在此次提交中，需要删除
        List<Long> needDeleteDrawingIdList = new ArrayList<>(homeBuilderDrawingCategoryAuditMap.keySet());
        removeByReportIdAndDrawingId(reportId, needDeleteDrawingIdList);
        // 如果是审核未通过或待审核的图纸分类，则删除并发起审核
        return reSaveBatch(needResubmitList, reportId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reSaveBatch(List<HomeBuilderDrawingCategoryAuditDTO> list, Long reportId) {
        // 报馆ID，图纸类型ID删除图纸分类
        List<Long> drawingIdList = list
                .stream()
                .map(HomeBuilderDrawingCategoryAuditDTO::getDrawingId)
                .collect(Collectors.toList());
        removeByReportIdAndDrawingId(reportId, drawingIdList);
        // 批量保存图纸
        return saveBatch(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveByVenueDrawingCategoryAudit(VenueDrawingCategoryAuditDTO venueDrawingCategoryAuditDTO) {
        // 报馆ID与图纸id移除
        List<Long> drawingIdList = new ArrayList<>();
        drawingIdList.add(venueDrawingCategoryAuditDTO.getDrawingId());
        removeByReportIdAndDrawingId(venueDrawingCategoryAuditDTO.getVenueReportId(), drawingIdList);
        // 保存主场搭建商图纸分类审核记录
        HomeBuilderDrawingCategoryAuditDTO homeBuilderDrawingCategoryAuditDTO = toHomeBuilderDrawingCategoryAuditDTO(venueDrawingCategoryAuditDTO);
        return saveHomeBuilderDrawingCategoryAudit(homeBuilderDrawingCategoryAuditDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAuditStatus(HomeBuilderDrawingCategoryAuditDTO auditDTO) {
        log.info("updateAuditStatus - 审核图纸分类, auditDTO={}", auditDTO);
        HomeBuilderDrawingCategoryAudit audit = getById(auditDTO.getId());
        if (audit == null) {
            throw BizException.wrap(VenueServiceExceptionCode.HOME_BUILDER_DRAWING_CATEGORY_AUDIT_NOT_EXIST);
        }
        if (HomeBuilderDrawingCategoryAuditAuditStatusEnum.NOT_NEED_AUDIT.eq(audit.getAuditStatus())) {
            throw BizException.wrap(VenueServiceExceptionCode.DRAWING_CATEGORY_NOT_NEED_AUDIT.getCode(), "该图纸无需审核");
        }
        audit.setAuditStatus(auditDTO.getAuditStatus());
        audit.setAuditOpinion(auditDTO.getAuditOpinion());
        audit.setAuditTime(LocalDateTime.now());
        audit.setAuditUserId(auditDTO.getAuditUserId());
        audit.setAuditUserName(auditDTO.getAuditUserName());
        updateById(audit);
        // 查询搭建商报馆图纸是否全部审核通过
        List<HomeBuilderDrawingCategoryAudit> list = listByReportIdAndSource(audit.getReportId(), HomeBuilderDrawingCategoryAuditDrawingSourceEnum.BUILDER_REPORT);
        boolean builderReportSpaceAllApproved = isBuilderReportSpaceAllApproved(list);
        // 审核通过则更新到展会展厅图纸
        if (builderReportSpaceAllApproved) {
            exhibitionSpaceDrawingService.saveBatchByHomeBuilderDrawingCategoryAudit(list);
        }
        // 更新搭建商报馆图纸分类审核状态
        venueManageReportDrawingCategoryAuditService.updateVenueAuditStatusByHomeBuilderDrawingCategory(audit);
        // 保存审核历史
        CopyOptions copyOptions = CopyOptions
                .create()
                .setIgnoreProperties(CommonConstants.COMMON_IGNORE_PROPERTIES);
        HomeBuilderDrawingCategoryAuditHistoryDTO homeBuilderDrawingCategoryAuditHistoryDTO = BeanUtil.toBean(audit, HomeBuilderDrawingCategoryAuditHistoryDTO.class, copyOptions);
        homeBuilderDrawingCategoryAuditHistoryService.asyncSaveHistory(homeBuilderDrawingCategoryAuditHistoryDTO);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatchAuditStatus(List<HomeBuilderDrawingCategoryAuditDTO> auditDTOList) {
        log.info("updateBatchAuditStatus - 批量审核, auditDTOList={}", auditDTOList);
        // todo 待优化，批量提交，只走一次IO
        if (auditDTOList == null || auditDTOList.isEmpty()) {
            return false;
        }
        auditDTOList.forEach(this::updateAuditStatus);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByReportIdAndSource(Long reportId, HomeBuilderDrawingCategoryAuditDrawingSourceEnum drawingSource) {
        log.info("removeByReportIdAndSource - 报馆ID删除图纸分类审核, reportId={}, drawingSource={}", reportId, drawingSource);
        List<HomeBuilderDrawingCategoryAudit> list = listByReportIdAndSource(reportId, drawingSource);
        if (list == null || list.isEmpty()) {
            return false;
        }
        // 批量移除图纸分类
        removeByIdsOfLogic(list);
        // 移除图纸
        homeBuilderDrawingAuditService.removeByReportIdAndType(reportId, drawingSource);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByReportIdAndDrawingId(Long reportId, List<Long> drawingIdList) {
        if (drawingIdList == null || drawingIdList.isEmpty()) {
            return false;
        }
        HomeBuilderDrawingCategoryAuditDTO query = new HomeBuilderDrawingCategoryAuditDTO();
        query.setReportId(reportId);
        query.setDrawingIdList(drawingIdList);
        List<HomeBuilderDrawingCategoryAudit> list = listHomeBuilderDrawingCategoryAudit(query);
        if (list == null || list.isEmpty()) {
            return false;
        }
        removeByIdsOfLogic(list);
        return homeBuilderDrawingAuditService.removeByReportIdAndDrawingId(reportId, drawingIdList);
    }

    private QueryWrapper<HomeBuilderDrawingCategoryAudit> createQueryWrapper(HomeBuilderDrawingCategoryAuditDTO query) {
        QueryWrapper<HomeBuilderDrawingCategoryAudit> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(HomeBuilderDrawingCategoryAudit::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(query.getExhibitionManageId() != null, HomeBuilderDrawingCategoryAudit::getExhibitionManageId, query.getExhibitionManageId())
                .eq(StrUtil.isNotBlank(query.getSpaceCode()), HomeBuilderDrawingCategoryAudit::getSpaceCode, query.getSpaceCode())
                .eq(StrUtil.isNotBlank(query.getSiteCode()), HomeBuilderDrawingCategoryAudit::getSiteCode, query.getSiteCode())
                .eq(StrUtil.isNotBlank(query.getSiteName()), HomeBuilderDrawingCategoryAudit::getSiteName, query.getSiteName())
                .eq(query.getDrawingId() != null, HomeBuilderDrawingCategoryAudit::getDrawingId, query.getDrawingId())
                .like(StrUtil.isNotBlank(query.getDrawingName()), HomeBuilderDrawingCategoryAudit::getDrawingName, query.getDrawingName())
                .eq(query.getAuditStatus() != null, HomeBuilderDrawingCategoryAudit::getAuditStatus, query.getAuditStatus())
                .eq(StrUtil.isNotBlank(query.getDrawingType()), HomeBuilderDrawingCategoryAudit::getDrawingType, query.getDrawingType())
                .eq(query.getReportId() != null, HomeBuilderDrawingCategoryAudit::getReportId, query.getReportId())
                .eq(query.getDrawingSource() != null, HomeBuilderDrawingCategoryAudit::getDrawingSource, query.getDrawingSource())
                .in(query.getDrawingIdList() != null && !query.getDrawingIdList().isEmpty(), HomeBuilderDrawingCategoryAudit::getDrawingId, query.getDrawingIdList())
        ;
        return queryWrapper;
    }

    /**
     * 一键报馆图纸分类转换为主场搭建商图纸审核分类.
     *
     * @param venueDrawingCategoryAuditDTO the venue drawing category audit dto
     * @return the home builder drawing category audit dto
     */
    public HomeBuilderDrawingCategoryAuditDTO toHomeBuilderDrawingCategoryAuditDTO(VenueDrawingCategoryAuditDTO venueDrawingCategoryAuditDTO) {
        HomeBuilderDrawingCategoryAuditDTO homeBuilderDrawingCategoryAuditDTO = new HomeBuilderDrawingCategoryAuditDTO();
        homeBuilderDrawingCategoryAuditDTO.setReportId(venueDrawingCategoryAuditDTO.getVenueReportId());
        homeBuilderDrawingCategoryAuditDTO.setDrawingSource(HomeBuilderDrawingCategoryAuditDrawingSourceEnum.HOME_REPORT);
        homeBuilderDrawingCategoryAuditDTO.setExhibitionManageId(venueDrawingCategoryAuditDTO.getExhibitionManageId());
        homeBuilderDrawingCategoryAuditDTO.setExhibitionManageName(venueDrawingCategoryAuditDTO.getExhibitionManageName());
        homeBuilderDrawingCategoryAuditDTO.setSpaceCode(venueDrawingCategoryAuditDTO.getSpaceCode());
        homeBuilderDrawingCategoryAuditDTO.setSpaceName(venueDrawingCategoryAuditDTO.getSpaceName());
        homeBuilderDrawingCategoryAuditDTO.setDrawingId(venueDrawingCategoryAuditDTO.getDrawingId());
        homeBuilderDrawingCategoryAuditDTO.setDrawingName(venueDrawingCategoryAuditDTO.getDrawingName());
        homeBuilderDrawingCategoryAuditDTO.setDrawingSort(venueDrawingCategoryAuditDTO.getDrawingSort());
        homeBuilderDrawingCategoryAuditDTO.setDrawingType(venueDrawingCategoryAuditDTO.getDrawingType());
        homeBuilderDrawingCategoryAuditDTO.setAuditStatus(HomeBuilderDrawingCategoryAuditAuditStatusEnum.NOT_NEED_AUDIT);
        homeBuilderDrawingCategoryAuditDTO.setHomeAuditStatus(HomeBuilderDrawingCategoryAuditAuditStatusEnum.NOT_NEED_AUDIT.getCode());

        List<VenueDrawingAuditDTO> venueDrawingAuditList = venueDrawingCategoryAuditDTO.getVenueDrawingAuditList();
        if (venueDrawingAuditList != null && !venueDrawingAuditList.isEmpty()) {
            List<HomeBuilderDrawingAuditDTO> homeBuilderDrawingAuditList = new ArrayList<>();
            for (VenueDrawingAuditDTO venueDrawingAuditDTO: venueDrawingAuditList) {
                HomeBuilderDrawingAuditDTO homeBuilderDrawingAuditDTO = toHomeBuilderDrawingAuditDTO(venueDrawingAuditDTO);
                homeBuilderDrawingAuditList.add(homeBuilderDrawingAuditDTO);
            }
            homeBuilderDrawingCategoryAuditDTO.setDrawingAuditList(homeBuilderDrawingAuditList);
        }
        return homeBuilderDrawingCategoryAuditDTO;
    }

    /**
     * 一键报馆图纸审核 转为 主场搭建商图纸
     *
     * @param venueDrawingAuditDTO the venue drawing audit dto
     * @return the home builder drawing audit dto
     */
    public HomeBuilderDrawingAuditDTO toHomeBuilderDrawingAuditDTO(VenueDrawingAuditDTO venueDrawingAuditDTO) {
        HomeBuilderDrawingAuditDTO homeBuilderDrawingAuditDTO = new HomeBuilderDrawingAuditDTO();
        homeBuilderDrawingAuditDTO.setReportId(venueDrawingAuditDTO.getVenueReportId());
        homeBuilderDrawingAuditDTO.setDrawingSource(HomeBuilderDrawingCategoryAuditDrawingSourceEnum.HOME_REPORT.getCode());
        homeBuilderDrawingAuditDTO.setSpaceCode(venueDrawingAuditDTO.getSpaceCode());
        homeBuilderDrawingAuditDTO.setSpaceName(venueDrawingAuditDTO.getSpaceName());
        homeBuilderDrawingAuditDTO.setExhibitionManageId(venueDrawingAuditDTO.getExhibitionManageId());
        homeBuilderDrawingAuditDTO.setExhibitionManageName(venueDrawingAuditDTO.getExhibitionManageName());
        homeBuilderDrawingAuditDTO.setDrawingId(venueDrawingAuditDTO.getDrawingId());
        homeBuilderDrawingAuditDTO.setDrawingName(venueDrawingAuditDTO.getDrawingName());
        homeBuilderDrawingAuditDTO.setImageUrl(venueDrawingAuditDTO.getImageUrl());
        return homeBuilderDrawingAuditDTO;
    }
}
